package com.example.bes.springboot.nacos.discovery.war.config;

import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
import com.alibaba.cloud.nacos.registry.NacosRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;

@Configuration
public class NacosRegistryConfig {

    private static final Logger log = LoggerFactory.getLogger(NacosRegistryConfig.class);

    @Autowired
    private NacosRegistration nacosRegistration;

    @Autowired
    private NacosAutoServiceRegistration nacosAutoServiceRegistration;

    @PostConstruct
    public void nacosServerRegister() {
        try {
            String besPortStr = getBesPort();
            if (Objects.nonNull(besPortStr)) {
                Integer besPort = Integer.valueOf(besPortStr);
                nacosRegistration.setPort(besPort);
                nacosAutoServiceRegistration.start();
            }
        } catch (MalformedObjectNameException e) {
            log.error("Get BES server port faild, exception info: {}", e);
        }
    }

    private static String getBesPort() throws MalformedObjectNameException {
        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), null);
        Iterator<ObjectName> iterator = objectNames.iterator();
        // @TODO 如果有多有 HTTP 监听器的话，需要制定一定的端口规则去区分，如果使用bes默认的 19*** 可以使用如下过滤方式
        while (iterator.hasNext()) {
            String port = iterator.next().getKeyProperty("port");
            if (!port.startsWith("19")) {
                return port;
            }
        }
        return null;
    }
}
